#pragma once

//#include <atlbase.h>
#include <string>
#include <memory>
#include "GlobalDefs.h"
#include <streams.h>

using namespace std;

__interface IGraphBuilder;
__interface IBaseFilter;
class DDrawH264Play;
#ifdef SUPPORT_H264
class H264DecodeFilter;
#endif

typedef enum PlayerType
{
	PLAYERTYPE_WINDOWS_MEDIA_FILE,
	PLAYERTYPE_H264_FILE_STREAM,
	PLAYERTYPE_H264_BIT_STREAM,
	PLAYERTYPE_RAW_FRAME_STREAM,
} PLAYERTYPE;

class MutableClock : public CBaseReferenceClock
{
public:
	MutableClock() : CBaseReferenceClock("Mutable Clock", NULL, NULL), m_rate(1.0), m_lastValue(0) { AddRef();}

	virtual REFERENCE_TIME GetPrivateTime()
	{
		if (m_lastValue == 0)
		{
			m_lastActual = CBaseReferenceClock::GetPrivateTime();
			m_lastValue = m_lastActual;
		}
		else
		{
			REFERENCE_TIME currTime = CBaseReferenceClock::GetPrivateTime();
			m_lastValue += REFERENCE_TIME(double(currTime - m_lastActual) * m_rate);
			m_lastActual = currTime;
		}

		return m_lastValue;
	}

	void SetRate(double rate) { m_rate = rate;}

private:
	REFERENCE_TIME m_lastValue;
	REFERENCE_TIME m_lastActual;
	double m_rate;
};


class DirectShowPlayer
{
public:
	DirectShowPlayer(void);
	virtual ~DirectShowPlayer(void);

	int Start();
	void Stop();
	void Pause();
	int SnapShot(const char *filename);
	int GetSnapShot(char *buf, UINT bufSize);
	int GetSnapShotSize();

	int UpdateVideoWindow();
	int GetPlaybackBitrate();
	int GetTotalFrame();
	int GetActualFps();
	int SetDisplayRect(const RECT &rect);

	int GetActualVideoSize(int *width, int *height);
	int SetDrawCallback(DRAWCALLBACK drawCallback, long param);
	int SetDecodeCallback(DECODECALLBACK decodeCallback, long param, bool needDisplay);
	//int SetFrameCallback(FrameCALLBACK decodeCallback, long param);//yb added for chengdu uestc,20111109 
	int ChangePlaybackFps(UINT fps);
	int SetPlaybackRate(double rate);

	int GetFilePlayTime(DWORD *milliseconds);
	int GetFileCurrTime(DWORD *milliseconds);
	int StepForward();
	int StepBack();

	int DisableAllCallback();

#ifdef SUPPORT_H264
	int CreateWindowsMediaPlayer(const char *sourceName);
	int CreateH264FileStreamPlayer(const char *sourceName, UINT fps);
	int CreateH264StreamPlayer(PLAYBACKSESSION session, DataProviderCallBack, UINT fps, LPVOID param = 0, UINT width = 0, UINT height = 0);
#endif
	int CreateRawStreamPlayer(PLAYBACKSESSION session, DataProviderCallBack, UINT fps, LPVOID param = 0, UINT width = 0, UINT height = 0);

	void SetFPS(UINT fps) { _fps = fps;}
	void SetOutputPosition(HWND hwnd, int x, int y, int width, int height);
	void ChangeVolume(UINT volume);
	bool IsPlaying();
	bool Seek(DWORD position);

	bool HasAudio();
	UINT GetFPS() { return _fps;}
	bool GetVideoSize(int *width, int *height);

	PLAYERTYPE GetPlayerType() { return _playerType;}

protected:
	CComPtr<IGraphBuilder> _graphBuilder;
	CComPtr<IBaseFilter> _fileSourceFilter;
	CComPtr<IBaseFilter> _vmr9;
	auto_ptr<DDrawH264Play> _h264Play;
#ifdef SUPPORT_H264
	auto_ptr<H264DecodeFilter> _h264DecodeFilter;
#endif

	PLAYERTYPE _playerType;
	string _sourceName;
	DWORD _format;
	UINT _width, _height;
	UINT _destWidth, _destHeight;
	UINT _fps;
	DataProviderCallBack _dataProvider;

	PLAYBACKSESSION m_session;

	HWND _parentWindow;
	int _x, _y, _outputWidth, _outputHeight;
	LPVOID _param;

	bool _isCreated;
	MutableClock _clock;

	int InitializePlayer();
	void DestroyPlayer();

private:
	bool CreateGraphBuilder();
	void ReleaseAll();
	void UpdateOutputPosition();
	bool RenderAllPin();
};
